package cn.opencodes.framework.core.utils;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import cn.opencodes.framework.core.shiro.AuthcSecretFilter;
import cn.opencodes.framework.core.shiro.AuthcTokenFilter;
import cn.opencodes.framework.core.vo.UserAgent;
import cn.opencodes.framework.core.vo.UserRoot;
import cn.opencodes.framework.tools.utils.JsonUtils;
import cn.opencodes.framework.tools.utils.StringUtils;
import cn.opencodes.framework.tools.utils.UserAgentUtil;
import cn.opencodes.framework.tools.vo.R;
/**
 * 基于继承Shrio封装的WebUtis对Servlet操作辅助类
 * @author hj
 */
public class WebUtils extends org.apache.shiro.web.util.WebUtils{
	private static final Logger logger = LoggerFactory.getLogger(WebUtils.class);
	private static final String USER_KEY = "al_currentuser";
	
	/**
	* 解析浏览器的user agent字符串，返回UserAgentInfo对象。<br/>
	* 如果user agent为空，返回null。如果解析失败，也直接返回null。
	* @param request
	*/
	public static UserAgent analyticUserAgent(HttpServletRequest request) {
		String userAgent = request.getHeader("user-agent");
		return UserAgentUtil.analyticUserAgent(userAgent);
	}
	

	public static HttpServletRequest getHttpServletRequest() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
	}
	
	public static Object getAttribute (String name){
		return getHttpServletRequest().getAttribute(name);
	}
	
	public static void setAttribute(String userKey, Object obj) {
		getHttpServletRequest().setAttribute(userKey, obj);
	}
	
	public static String getRealPath (){
		return getHttpServletRequest().getServletContext().getRealPath("/");
	}
	
	public static String getContextPath (){
		return getHttpServletRequest().getServletContext().getContextPath();
	}
	
	public static void write(HttpServletResponse response,Object o)throws Exception{
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out=response.getWriter();
		out.println(o.toString());
		out.flush();
		out.close();
	}
	
	public static void write(ServletResponse response, int code, String msg){
    	HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setContentType("application/json;charset=utf-8");
        try {
            String json = JsonUtils.toJson( R.error(code, msg) );
            httpResponse.getWriter().print(json);
        } catch (IOException e1) {
        	e1.printStackTrace();
        }
    }
	
	public static void write(ServletResponse response, R r){
    	HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setContentType("application/json;charset=utf-8");
        try {
            String json = JsonUtils.toJson(r);
            httpResponse.getWriter().print(json);
        } catch (IOException e1) {
        	e1.printStackTrace();
        }
    }
	
	public static void setUser(UserRoot user){
		setAttribute(USER_KEY, user);
	}
	
	public static UserRoot getUser(){
		UserRoot user = (UserRoot)getAttribute(USER_KEY);
		if (user == null) {
			user = new UserRoot();
			String appKey = getRequestAppKey(getHttpServletRequest());
			if (StringUtils.isNotBlank(appKey)) {
				user.setUsername(appKey);
			}else {
				user.setUsername(getIpAddr());
			}
		}
		return user;
	}

	/**
	 * 获取IP地址
	 * 使用Nginx等反向代理软件， 则不能通过request.getRemoteAddr()获取IP地址
	 * 如果使用了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP地址，X-Forwarded-For中第一个非unknown的有效IP字符串，则为真实IP地址
	 */
	public static String getIpAddr(HttpServletRequest request) {
		String ip = null;
        try {
            ip = request.getHeader("x-forwarded-for");
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } catch (Exception e) {
        	logger.error("获取客户端IP异常： ", e);
        }
        return ip;
	}

	/**
	 * 获取IP地址
	 * 使用Nginx等反向代理软件， 则不能通过request.getRemoteAddr()获取IP地址
	 * 如果使用了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP地址，X-Forwarded-For中第一个非unknown的有效IP字符串，则为真实IP地址
	 */
	public static String getIpAddr() {
		HttpServletRequest request = getHttpServletRequest();
        return getIpAddr(request);
    }
	
	/**
	 * 从request中获得参数Map，并返回可读的Map
	 * 
	 * @param request
	 */
	@SuppressWarnings({"rawtypes" })
	public static Map<String, Object> extractToMap(HttpServletRequest request) {
	    // 参数Map
	    Map properties = request.getParameterMap();
	    // 返回值Map
	    Map<String, Object> returnMap = new HashMap<>();
	    Iterator entries = properties.entrySet().iterator();
	    Map.Entry entry;
	    String name = null;
	    Object value = null;
	    while (entries.hasNext()) {
	        entry = (Map.Entry) entries.next();
	        name = (String) entry.getKey();
	        value = entry.getValue();
	        if(value == null){
	            continue;
	        }else if(value instanceof String[]){
	            String[] values = (String[])value;
	            StringBuilder vs = new StringBuilder();
	            for(int i=0;i<values.length;i++){
	                vs.append(values[i]).append(",");
	            }
	            vs.deleteCharAt(vs.length()-1);
	            value = vs.toString();
	        }
	        
	        returnMap.put(name, value);
	    }
	    return returnMap;
	}
	
	/**
     * 判断当前是否是AJAX请求
     * @param request
     */
    public static boolean isAjax(HttpServletRequest request){
    	String type = request.getHeader("X-Requested-With") == null ? "" : request.getHeader("X-Requested-With");  
    	if (type.equals("XMLHttpRequest")) {  
            // 处理ajax请求, 设置响应header：超时标识以及重定向路径  
            return true;
        } else {  
            // 普通请求直接进行redirect  
            return false;  
        } 
    }
    
    /** 获取请求的AppKey */
    public static String getRequestAppKey(ServletRequest request){
    	HttpServletRequest httpRequest = WebUtils.toHttp(request);
        //从header中获取
        String token = httpRequest.getHeader(AuthcSecretFilter.HEADER_APP_KEY);
        //如果header中不存在则从参数中获取token
        if(StringUtils.isBlank(token)){
            token = httpRequest.getParameter(AuthcSecretFilter.HEADER_APP_KEY);
        }
        return token;
    }
    
    /** 获取请求的AppSecret */
    public static String getRequestAppSecret(ServletRequest request){
    	HttpServletRequest httpRequest = WebUtils.toHttp(request);
    	//从header中获取
    	String token = httpRequest.getHeader(AuthcSecretFilter.HEADER_SECRET_KEY);
    	//如果header中不存在则从参数中获取token
    	if(StringUtils.isBlank(token)){
    		token = httpRequest.getParameter(AuthcSecretFilter.HEADER_SECRET_KEY);
    	}
    	return token;
    }
    
    /** 获取请求的token */
    public static String getRequestToken(ServletRequest request){
    	HttpServletRequest httpRequest = WebUtils.toHttp(request);
        //从header中获取token
        String token = httpRequest.getHeader(AuthcTokenFilter.HEADER_TOKEN_KEY);
        //如果header中不存在token，则从参数中获取token
        if(StringUtils.isBlank(token)){
            token = httpRequest.getParameter(AuthcTokenFilter.HEADER_TOKEN_KEY);
        }
        return token;
    }

}
